package com.hissy.common.redis;

import java.util.function.Function;

import com.alibaba.fastjson.JSON;

/**
 * Created by zhangyanfei on 2017/10/26.
 * Jedis锁构建工厂
 *
 * @author zhangyanfei
 * @date 2017/10/26
 */
/**
 * JedisLock构建工厂
 * <pre> {@code
 *  @Component
 *  public class DefaultJedisLockFactory extends AbstractJedisLockFactory {
 *      DefaultJedisLockFactory(@Value("common") String namespace, @Value("default") String keyPrefix) {
 *           super(namespace, keyPrefix);
 *      }
 *  }}</pre>
 */
public abstract class AbstractJedisLockFactory {
    protected String namespace;
    protected String keyPrefix;
    protected int expiryTimeMillis;
    public static final String LOCK_KEY_SPLITOR = "/";

    /**
     * JedisLock构建工厂
     *
     * @param namespace 命名空间，推荐注入服务名
     * @param keyPrefix lockkey前缀，推荐使用业务含义描述，类似：order、trade...
     */
    protected AbstractJedisLockFactory(String namespace, String keyPrefix) {
        this(namespace, keyPrefix, JedisLock.DEFAULT_EXPIRY_TIME_MILLIS);
    }

    /**
     * JedisLock构建工厂
     *
     * @param namespace        命名空间，推荐注入服务名
     * @param keyPrefix        lockkey前缀，推荐使用业务含义描述，类似：order、trade...
     * @param expiryTimeMillis 锁有效期
     */
    protected AbstractJedisLockFactory(String namespace, String keyPrefix, int expiryTimeMillis) {
        this.namespace = namespace;
        this.keyPrefix = keyPrefix;
        this.expiryTimeMillis = expiryTimeMillis;
    }

    /**
     * 构建Lock
     *
     * @param func   自定义的Key构造函数
     * @param params
     * @return
     */
    public JedisLock buildLock(Function<Object[], String> func, Object... params) {
        return new JedisLock(namespace, lockKeyPostProcess(func.apply(params)), expiryTimeMillis);
    }

    /**
     * 默认的key构造
     *
     * @param params
     * @return
     */
    public JedisLock buildLock(Object... params) {
        String identity = params != null ?
            (params.length == 1 ? JSON.toJSONString(params[0]) : JSON.toJSONString(params))
            : "";
        return new JedisLock(namespace, lockKeyPostProcess(identity), expiryTimeMillis);
    }

    /**
     * 默认Key构造
     *
     * @param param
     * @return
     */
    public JedisLock buildLock(int param) {
        return new JedisLock(namespace, lockKeyPostProcess(String.valueOf(param)), expiryTimeMillis);
    }

    /**
     * 默认Key构造
     *
     * @param param
     * @return
     */
    public JedisLock buildLock(boolean param) {
        return new JedisLock(namespace, lockKeyPostProcess(String.valueOf(param)), expiryTimeMillis);
    }

    /**
     * 默认Key构造
     *
     * @param param
     * @return
     */
    public JedisLock buildLock(double param) {
        return new JedisLock(namespace, lockKeyPostProcess(String.valueOf(param)), expiryTimeMillis);
    }

    /**
     * 默认Key构造
     *
     * @param param
     * @return
     */
    public JedisLock buildLock(float param) {
        return new JedisLock(namespace, lockKeyPostProcess(String.valueOf(param)), expiryTimeMillis);
    }

    /**
     * 默认Key构造
     *
     * @param param
     * @return
     */
    public JedisLock buildLock(short param) {
        return new JedisLock(namespace, lockKeyPostProcess(String.valueOf(param)), expiryTimeMillis);
    }

    /**
     * 默认Key构造
     *
     * @param param
     * @return
     */
    public JedisLock buildLock(long param) {
        return new JedisLock(namespace, lockKeyPostProcess(String.valueOf(param)), expiryTimeMillis);
    }

    /**
     * 默认Key构造
     *
     * @param param
     * @return
     */
    public JedisLock buildLock(byte param) {
        return new JedisLock(namespace, lockKeyPostProcess(String.valueOf(param)), expiryTimeMillis);
    }

    /**
     * 默认Key构造
     *
     * @param param
     * @return
     */
    public JedisLock buildLock(char param) {
        return new JedisLock(namespace, lockKeyPostProcess(String.valueOf(param)), expiryTimeMillis);
    }

    /**
     * lockKey构建后置处理，推荐进行key业务属性
     *
     * @param identify lockkey标识
     * @return
     */
    protected String lockKeyPostProcess(String identify) {
        return keyPrefix + LOCK_KEY_SPLITOR + identify;
    }
}
